package light.network;

import java.nio.ByteBuffer;

import light.network.object.PackObject;

import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PackProtocal extends Protocol {
	
	private static Logger logger = LoggerFactory.getLogger(PackProtocal.class);
	
	public static final int HeaderFlag = 12345;
	public static final int MaxLength = 1024*32;


	/**
	 * 验证数据包格式并返回它的声明长度
	 * @param buf
	 * @return 如果格式正确，返回数据包的声明长度；如果格式不正确，返回-1
	 */
	public static int getPackLength(ByteBuffer buf)
	{
		try
		{
			int h = buf.getInt();
			if(h!=HeaderFlag)
				return -1;
			if(h>MaxLength)
				return -1;
			int len = buf.getInt();
			if(len>0)
				return len;
		}
		catch(Exception err)
		{
			logger.warn("Receive a wrong format package, cannot validate it's length.");
			err.printStackTrace();
		}
		return -1;
	}

	public static void putPackHeader(ByteBuffer buffer, int packLen)
	{
		buffer.putInt(HeaderFlag);
		buffer.putInt(packLen);
	}
	
	
	public static byte[] createByteArray(String msg)
	{
		ByteBuffer buf = ByteBuffer.allocate(msg.length()+8);
		buf.putInt(HeaderFlag);
		buf.putInt(msg.length());
		buf.put(msg.getBytes());
		buf.flip();
		return buf.array();
	}
	

	public static ByteBuffer createPack(PackObject data)
	{
		byte[] hByte = data.getHeader().toString().getBytes();
		ByteData ds = data.array();
		int dLen = ds==null?0:ds.length();
		int packLen = hByte.length+dLen+4;
		ByteBuffer buf = ByteBuffer.allocate(packLen+8);
		putPackHeader(buf, packLen);
		buf.putInt(hByte.length);
		buf.put(hByte);
		if(dLen>0)
		{
			buf.put(ds.array(), ds.start(), ds.length());
		}
		buf.flip();
		return buf;
	}
	
	/**
	 * 将数据包解码成对象
	 * @param data
	 * @return
	 */
	public static PackObject wrap(Packet data)
	{
		ByteData d = data.data();
		return wrap(ByteBuffer.wrap(d.array(), d.start(), d.length()));
	}
	
	/**
	 * 将数据包解码成对象
	 * @param data
	 * @return
	 */
	public static PackObject wrap(ByteBuffer data)
	{
		int headerLength = data.getInt();//ByteConvertor.getInt(data, 0);
		String headerString = new String(data.array(), data.position(), headerLength);
		//参数映射
		JSONObject h = null;
		try {
			h = new JSONObject(headerString);
		} catch (JSONException e) {
			throw new RuntimeException(e);
		}
		PackObject ob = new PackObject(h);
		ob.setHeaderLength(headerLength);
		ob.setHeader(h);
		int offset = data.position()+headerLength;
		ob.setData(new ByteData(data.array(), offset, data.limit()-offset));
		return ob;
	}
//	/**
//	 * 将数据包解码成对象
//	 * @param data
//	 * @return
//	 */
//	public static PackObject wrap(ByteData data)
//	{
//		String headerString = new String(data.array(), data.start(), data.length());
//		//参数映射
//		JSONObject h = null;
//		try {
//			h = new JSONObject(headerString);
//		} catch (JSONException e) {
//			throw new RuntimeException(e);
//		}
//		PackObject ob = new PackObject(h);
//		ob.setHeaderLength(headerLength);
//		ob.setHeader(h);
//		int offset = data.position()+headerLength;
//		ob.setData(new ByteData(data.array(), offset, data.limit()-offset));
//		return ob;
//	}
	
	/**
	 * 将数据包解码成对象
	 * @param data
	 * @return
	 */
	public static PackObject wrapUDP(ByteBuffer data)
	{
		int headerLength = data.getInt();//ByteConvertor.getInt(data, 0);
		String headerString = new String(data.array(), data.position(), headerLength);
		//参数映射
		JSONObject h = null;
		try {
			h = new JSONObject(headerString);
		} catch (JSONException e) {
			throw new RuntimeException(e);
		}
		PackObject ob = new PackObject(h);
		ob.setHeaderLength(headerLength);
		ob.setHeader(h);
		int offset = data.position()+headerLength;
		ob.setData(new ByteData(data.array(), offset, data.limit()-offset));
		return ob;
	}

	/**
	 * 将对象编码成数据包
	 * @param data
	 * @param buf
	 * @return
	 */
	@SuppressWarnings("unused")
	private static ByteBuffer unwrap(PackObject data, ByteBuffer buf)
	{
		buf.clear();
		byte[] hByte = data.getHeader().toString().getBytes();
		ByteData ds = data.array();
		int dLen = ds==null?0:ds.length();
		int packLen = hByte.length+dLen+4;
		putPackHeader(buf, packLen);
		buf.putInt(hByte.length);
		buf.put(hByte);
		if(dLen>0)
		{
			buf.put(ds.array(), ds.start(), ds.length());
		}
		buf.flip();
		return buf;
	}
	
	/**
	 * 将对象编码成数据包
	 * @param data
	 * @param buf
	 * @return
	 */
	public static Packet unwrap(PackObject data, Packet buf)
	{
		buf.clear();
		byte[] hByte = data.getHeader().toString().getBytes();
		ByteData ds = data.array();
		int dLen = ds==null?0:ds.length();
		buf.putInt(hByte.length);
		buf.put(hByte);
		if(dLen>0)
		{
			buf.put(ds.array(), ds.start(), ds.length());
		}
		buf.flip();
		//System.out.println("len:"+hByte.length+","+buf.getInt(0));
		return buf;
	}

	/**
	 * 将对象编码成数据包
	 * @param data
	 * @return
	 */
	public static Packet unwrapUDP(PackObject data)
	{
		byte[] hByte = data.getHeader().toString().getBytes();
		ByteData ds = data.array();
		int dLen = ds==null?0:ds.length();
		Packet buf = UdpPacket.allocate(hByte.length+dLen+4);
		buf.putInt(hByte.length);
		buf.put(hByte);
		if(dLen>0)
		{
			buf.put(ds.array(), ds.start(), ds.length());
		}
		buf.flip();
		return buf;
	}
	
	/**
	 * 将对象编码成数据包
	 * @param data
	 * @return
	 */
	public static Packet unwrapTcp(PackObject data)
	{
		byte[] hByte = data.getHeader().toString().getBytes();
		ByteData ds = data.array();
		int dLen = ds==null?0:ds.length();
		Packet buf = TcpPacket.allocate(dLen+ds.length());
		buf.put(hByte);
		if(dLen>0)
		{
			buf.put(ds.array(), ds.start(), ds.length());
		}
		buf.flip();
		return buf;
	}

//	public static ByteBuffer unwrapUDP(PackObject data, ByteBuffer buf)
//	{
//		buf.clear();
//		byte[] hByte = data.getHeader().toString().getBytes();
//		ByteData ds = data.getData();
//		int dLen = ds==null?0:ds.getLength();
//		buf.putInt(hByte.length);
//		buf.put(hByte);
//		if(dLen>0)
//		{
//			buf.put(ds.getData(), ds.getStart(), ds.getLength());
//		}
//		buf.flip();
//		return buf;
//	}
}
